package elec315.chatroom.net;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import elec315.chatroom.core.dispatcher.MessageDispatcher;
import elec315.chatroom.msg.BaseMsg;

public class ClientSocketHandler implements Runnable, SocketHandler {

	private static final Log logger = LogFactory.getLog(ClientSocketHandler.class);

	private MessageDispatcher messageDispatcher;

	private Socket socket;
	private ObjectInputStream fromServer;
	private ObjectOutputStream toServer;
	private String userId;

	public ClientSocketHandler(Socket socket) throws IOException {
		this.socket = socket;
		toServer = new ObjectOutputStream(socket.getOutputStream());
	}

	public void setMessageDispatcher(MessageDispatcher messageDispatcher) {
		this.messageDispatcher = messageDispatcher;
	}

	public void run() {
		logger.debug("ClientSocketHandler is started.");
		try {
			fromServer = new ObjectInputStream(socket.getInputStream());
			while (true) {
				Object obj = null;
				while ((obj = fromServer.readObject()) != null) {
					if (obj instanceof BaseMsg) {
						BaseMsg baseMsg = (BaseMsg) obj;
						messageDispatcher.onMessage(baseMsg, this);
					}
				}
			}
		} catch (Exception ex) {
			logger.error(ex, ex);
		} finally {
			try {
				fromServer.close();
				toServer.close();
				socket.close();
				System.out.println("Server connection lost.");
				System.exit(0);
			} catch (IOException ex) {
				logger.error(ex, ex);
			}
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see elec315.chatroom.net.SocketHandler#writeMessage(elec315.chatroom.msg.BaseMsg)
	 */
	public void writeMessage(BaseMsg baseMsg) {
		synchronized (toServer) {
			try {
				toServer.writeObject(baseMsg);
				toServer.flush();
			} catch (IOException ex) {
				logger.error(ex, ex);
			}
		}
	}

	public String getUserId() {
		return userId;
	}

	public void setUserId(String userId) {
		this.userId = userId;
	}

}
